package errors

import (
	"fmt"
	"io"
)

type multiEx []error

func (e multiEx) Error() string {
	switch len(e) {
	case 0:
		return ""
	case 1:
		return (e)[0].Error()
	default:
		l := len(e) - 1
		return fmt.Sprintf("%s (+%d...)", (e)[l].Error(), l)
	}
}

func (e multiEx) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			for _, err := range e {
				_, _ = fmt.Fprintf(s, "%+v\n", err)
			}
			return
		}
		fallthrough
	case 's', 'q':
		_, _ = io.WriteString(s, e.Error())
	}
}

func (e multiEx) Is(target error) bool {
	for _, err := range e {
		if Is(err, target) {
			return true
		}
	}
	return false
}

func Multi(err error, errs ...error) error {
	var n multiEx
	if err != nil {
		n = Unfold(err)
	}
	for _, err := range errs {
		if es := Unfold(err); len(es) > 0 {
			n = append(n, es...)
		}
	}
	if len(n) > 0 {
		return n
	}
	return nil
}

func Unfold(err error) []error {
	if err != nil {
		var me multiEx
		if As(err, &me) {
			return me
		}
		return []error{err}
	}
	return nil
}

